package sqlTool

import (
	"errors"
	"fmt"
	"log"
	"reflect"
	"strings"
)

// GeneratorSQL 生成SQL
func GeneratorSQL(target any) (sql string, args []any, err error) {
	v := reflect.ValueOf(target)
	t := reflect.TypeOf(target)
	if v.Kind() != reflect.Struct {
		return "", nil, errors.New("只能对结构体生成SQL")
	}

	log.Printf("目标对象%v", target)

	//获取表明
	tableName := v.MethodByName("TableName").Call(nil)[0].String()

	sql = fmt.Sprintf("select * from %s ", tableName)

	var condition string

	for i := range v.NumField() {
		field := v.Field(i)
		fieldType := t.Field(i)

		//如果是结构体或者为空
		if field.Kind() == reflect.Struct {
			continue
		}

		//不是指针类型
		if field.Kind() != reflect.Pointer || field.IsNil() {
			continue
		}

		//如果是字符串类型
		if field.Elem().Kind() == reflect.String {
			condition += fmt.Sprintf(" and %s like ?", ToLowerField(fieldType.Name))
			args = append(args, fmt.Sprintf("%%%s%%", field.Elem().String()))
		}

		//其他类型
		if field.Elem().Kind() != reflect.String {
			condition += fmt.Sprintf(" and %s = ?", ToLowerField(fieldType.Name))
			args = append(args, field.Elem().Interface())
		}
	}

	if len(args) > 0 {
		sql += "where"
	}

	sql += strings.Replace(condition, "and", "", 1)

	return
}

// ToLowerField 转换小写加下划线
func ToLowerField(name string) string {
	var arr = make([]int32, 0)
	for index, val := range name {
		if val >= 'A' && val <= 'Z' {
			val -= 'A' - 'a'
			if index == 0 {
				arr = append(arr, val)
				continue
			}
			arr = append(arr, '_', val)
			continue
		}
		arr = append(arr, val)
	}
	return string(arr)
}

type PageInfo struct {
	List      any   `json:"list"`
	Count     int64 `json:"count"`
	TotalPage int64 `json:"totalPage"`
	PageSize  int   `json:"pageSize"`
	PageNum   int   `json:"pageNum"`
	IsFist    bool  `json:"isFist"`
	IsLast    bool  `json:"isLast"`
}

func ToPageStruct(list any, pageNum, pageSize int, count int64) (pageInfo PageInfo) {
	totalPage := count / int64(pageSize)
	if count%int64(pageSize) != 0 {
		totalPage++
	}

	pageInfo = PageInfo{
		List:      list,
		Count:     count,
		TotalPage: totalPage,
		PageSize:  pageSize,
		PageNum:   pageNum,
	}

	//判断是第一页还是最后一页
	if pageNum == 1 {
		pageInfo.IsFist = true
		pageInfo.IsLast = false
	} else if totalPage == int64(pageSize) {
		pageInfo.IsFist = false
		pageInfo.IsLast = true
	}

	return
}
